#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

typedef int (*popenfunc)(const char*, int, void*);
#define OUTPUTLINESIZE 256
/*
* popen a process, read each line of it's stdout and pass the line data to func cb.
* the line passed to cb may be not the entire line if the line's len is more then OUTPUTLINESIZE
*/
int popen_process(char *cmd, popenfunc func, void* args)
{
    FILE *pipefd = NULL;
    char buf[OUTPUTLINESIZE + 1] = {0};
    pipefd = popen(cmd, "r");
    if(pipefd == NULL) {
        fprintf(stderr, "%s popen faild, errno(%d), error(%s)\n", __FUNCTION__, errno, strerror(errno));
				return -1;
    }
	int line_num = 0;
    while(1) {
		if (fgets(buf, OUTPUTLINESIZE, pipefd) == NULL) {
			if (feof(pipefd))
				break;
			else {
				fprintf(stderr, "failed when read popen stream %s\n", strerror(errno));
				break;
			}
		}
		func(buf, line_num, args);
		line_num++;
    }

    int ret = pclose(pipefd); 
	if (ret == -1 || !WIFEXITED(ret) || WEXITSTATUS(ret) != 0) {
		if (ret == -1)
        	fprintf(stderr, "pclose failed, error(%s)\n", strerror(errno) );
		else if(!WIFEXITED(ret))
        	fprintf(stderr, "process(%s) was unabled to exit normally\n", cmd);
		else
        	fprintf(stderr, "process(%s) returned errno(%d)\n", cmd, WEXITSTATUS(ret));
        return -1;
    }
	return 0;
}

int func(const char* line, int line_num, void* args)
{
	fprintf(stderr, "%s\n", line);
	return 0;
}

int main(int argc, char** argv)
{
	if (argc <= 1) {
		fprintf(stderr, "usage process cmd\n");
		return -1;
	}
	fprintf(stdout, "cmd:%s\n", argv[1]);	
	popen_process(argv[1], func, NULL);
	return 0;
}